﻿using System;
using System.Data;
using System.Configuration;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Collections;
using System.Reflection;
using System.Web.DynamicData;
using System.Linq.Expressions;
using System.ComponentModel;
using System.Collections.Generic;
using System.Collections.Specialized;
using HibernateDynamicData.Adapter;

namespace HibernateDynamicData.UI
{
    public class SanaLinqDataSource : LinqDataSource
    {
        private SanaLinqDataSourceView view;

        public SanaLinqDataSource()
        {
            FieldInfo fi = typeof(LinqDataSource).GetField("_view", BindingFlags.Instance | BindingFlags.NonPublic);
            this.view = new SanaLinqDataSourceView(this, this.Context);
            fi.SetValue(this, view);
            if ((this.view != null) && base.IsTrackingViewState)
            {
                ((IStateManager)this.view).TrackViewState();
            }
        }

        private class SanaLinqDataSourceView : LinqDataSourceView
        {
            public const string LanguageParameterName = "Language";
            public const string WebsiteParameterName = "Website";

            public ParameterCollection ChannelParameters { get; private set; }

            private HttpContext httpContext;
            private SanaLinqDataSource owner;

            public SanaLinqDataSourceView(SanaLinqDataSource owner, HttpContext context)
                : base(owner, "DefaultView", context)
            {
                this.owner = owner;
                this.httpContext = context;
                this.ChannelParameters = new ParameterCollection();
            }

            protected override MemberInfo GetTableMemberInfo(Type contextType)
            {
                if (typeof(GenericNHibernateContext).IsAssignableFrom(contextType))
                    return new StubFieldInfo(this.TableName);
                else
                    return base.GetTableMemberInfo(contextType);
            }

            class StubFieldInfo : FieldInfo
            {
                private string name;

                public StubFieldInfo(string name)
                {
                    this.name = name;
                }

                public override object GetValue(object obj)
                {
                    return ((GenericNHibernateContext)obj).GetTable(name);
                }

                #region Not implemented (not needed)

                public override FieldAttributes Attributes
                {
                    get { throw new NotImplementedException(); }
                }

                public override RuntimeFieldHandle FieldHandle
                {
                    get { throw new NotImplementedException(); }
                }

                public override Type FieldType
                {
                    get { throw new NotImplementedException(); }
                }

                public override void SetValue(object obj, object value, BindingFlags invokeAttr, Binder binder, System.Globalization.CultureInfo culture)
                {
                    throw new NotImplementedException();
                }

                public override Type DeclaringType
                {
                    get { throw new NotImplementedException(); }
                }

                public override object[] GetCustomAttributes(Type attributeType, bool inherit)
                {
                    throw new NotImplementedException();
                }

                public override object[] GetCustomAttributes(bool inherit)
                {
                    throw new NotImplementedException();
                }

                public override bool IsDefined(Type attributeType, bool inherit)
                {
                    throw new NotImplementedException();
                }

                public override string Name
                {
                    get { throw new NotImplementedException(); }
                }

                public override Type ReflectedType
                {
                    get { throw new NotImplementedException(); }
                }

                #endregion
            }
        }
    }
}
